/*
** DirectX renderer for GSP260
**
** Revision: $Id: Renderer.h 17 2010-09-11 01:25:07Z Tim Brengle $
*/
#pragma once
#include <d3d9.h>
#pragma comment(lib, "d3d9.lib")
#include <d3dx9.h>
#pragma comment(lib, "d3dx9.lib")
#include <dxerr.h>
#pragma comment(lib, "dxerr.lib")
#include "Object.h"


#define SQUARED(x)		((x)*(x))
#define NUM_ELEMENTS(x)	(sizeof(x) / sizeof(x[0]))


/* Renderer uses the Singleton design pattern */


enum LIGHT_KIND
{
	AMBIENT,
	DIFFUSE,
	SPECULAR
};

enum SHADE_MODE
{
	FLAT = D3DSHADE_FLAT,
	GOURAUD = D3DSHADE_GOURAUD,
	PHONG = D3DSHADE_PHONG
};

enum FILL_MODE
{
	POINT_FILL = D3DFILL_POINT,
	WIREFRAME = D3DFILL_WIREFRAME,
	SOLID = D3DFILL_SOLID
};


/******************************************************************************\
*                               Renderer class                                 *
\******************************************************************************/
class Renderer
{
public:
	/*****************************************************\
	* Instance: return pointer to the singleton           *
	\*****************************************************/
	inline static Renderer* Instance()
	{
		static Renderer theRenderer;
		return &theRenderer;
	}


	/*****************************************************\
	* Destructor                                          *
	\*****************************************************/
	virtual ~Renderer();


	/*****************************************************\
	* InitializeD3D: start Direct3D in a window           *
	\*****************************************************/
	void InitializeD3D(HWND hWnd);


	/*****************************************************\
	* RenderOneFrame: draw everything for this frame      *
	\*****************************************************/
	void RenderOneFrame(ObjectList& objects);


	/*****************************************************\
	* Get/Set ViewPoint                                   *
	\*****************************************************/
	D3DXVECTOR3& GetViewPoint() { return *(&m_vViewPoint); }
	void SetViewPoint(D3DXVECTOR3& vNewViewPoint);

	
	/*****************************************************\
	* Get/Set Shading Mode: { FLAT, GOURAUD, PHONG }      *
	\*****************************************************/
	SHADE_MODE GetShadingMode() { return (SHADE_MODE)m_eShadeMode; }
	void SetShadingMode(SHADE_MODE eMode);


	/*****************************************************\
	* Get/Set Fill Mode: { POINT_FILL, SOLID, WIREFRAME } *
	\*****************************************************/

	FILL_MODE GetFillMode() { return (FILL_MODE)m_eFillMode; }
	void SetFillMode(FILL_MODE eMode);


	/*****************************************************\
	* LoadMeshFile: load a mesh from a .X file            *
	\*****************************************************/
	void LoadMeshFile(const char* cszXFile, ID3DXMesh*& pMesh);


	/*****************************************************\
	* LoadTextureFile: load a texture from an image file  *
	\*****************************************************/
	void LoadTextureFile(const char* cszTextureFile, IDirect3DTexture9*& pTexture);


	/*****************************************************\
	* Toggle booleans for demo features                   *
	\*****************************************************/
	void ToggleTextures() { m_bShowTextures = ! m_bShowTextures; }
	void ToggleSpinning() { m_bSpinning = ! m_bSpinning; }
	void ToggleMaterialDemo() { m_bMaterialDemo = ! m_bMaterialDemo; }
	void ToggleLightKind(LIGHT_KIND l);


private:
	/*****************************************************\
	* Member variables                                    *
	\*****************************************************/
	IDirect3DDevice9*	m_pD3DDevice;		// Direct3D device
	D3DXMATRIX			m_matView;			// VIEW transform matrix
	D3DXMATRIX			m_matProj;			// PROJECTION transform matrix
	HWND				m_hWnd;				// handle to the window being drawn
	float				m_fScreenWidth;		// width of the drawable area of the window
	float				m_fScreenHeight;	// height of the drawable area of the window
	D3DMATERIAL9		m_cDefaultMaterial;	// material to use when none specified
	D3DSHADEMODE		m_eShadeMode;		// current shading mode (D3DSHADE_FLAT, D3DSHADE_GOURAUD, or D3DSHADE_PHONG)
	D3DFILLMODE			m_eFillMode;		// current fill mode (D3DFILL_SOLID or D3DFILL_WIREFRAME)
	D3DXVECTOR3			m_vViewPoint;		// current eye position
	bool				m_bShowTextures;
	bool				m_bSpinning;
	bool				m_bMaterialDemo;
	D3DMATERIAL9		m_cDemoMaterial;	// material to use when demo is on
	bool				m_bShowAmbient;
	bool				m_bShowDiffuse;
	bool				m_bShowSpecular;
	D3DPRESENT_PARAMETERS m_PresentParams;

	/*****************************************************\
	* Private constructor & copy constructor              *
	\*****************************************************/
	Renderer();
	Renderer(const Renderer& copyFromMe);


	/*****************************************************\
	* Cleanup: destroy local objects, etc.                *
	\*****************************************************/
	void Cleanup();


	/*****************************************************\
	* CreateLight: directional light                      *
	\*****************************************************/
	void CreateLight();


	/*****************************************************\
	* CreateDefaultMaterial: what to use if none given    *
	\*****************************************************/
	void CreateMaterials();
};
